home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Found / FWString / Include / FWCharIt.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-08  |  16.7 KB  |  486 lines  |  [TEXT/MPS ]

  1. #ifndef FWCHARIT_H
  2. #define FWCHARIT_H
  3. //========================================================================================
  4. //
  5. //    File:                FWCharIt.h
  6. //    Release Version:    $ 1.0d11 $
  7. //
  8. //    Copyright:    (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #ifndef FWAUTODE_H
  13. #include "FWAutoDe.h"
  14. #endif
  15.  
  16. #ifndef FWPRIDEB_H
  17. #include "FWPriDeb.h"
  18. #endif
  19.  
  20. #ifndef FWCHARAC_H
  21. #include "FWCharac.h"
  22. #endif
  23.  
  24. #if FW_LIB_EXPORT_PRAGMAS
  25. #pragma lib_export on
  26. #endif
  27.  
  28. #define FW_DEBUG_TEXT_ITERATORS
  29.  
  30.  
  31. //========================================================================================
  32. //                            Design Notes for Text Readers
  33. //
  34. //    Text readers are designed to be as fast and light-weight as possible.  We assume
  35. //    that in over 90% of the usage of Text readers, the reader will be used to make
  36. //    one sequential pass through the data structure, operating on one character at a time.
  37. //    The first design goal is therefore:
  38. //        1) Make GetCharacterAndAdvance be as efficient as possible.
  39. //    In order to achieve full efficiency, we need to minimize overhead for error checking
  40. //    for reading past the end of the data structure.  We therefore set this requirement:
  41. //        2) Rely on a clear contract to minimize overhead.  It is not necessary for
  42. //        iterators to fail gracefully when misused.
  43. //    As stated above, in 90% of the cases, the text is read in one forward pass.  However,
  44. //  reading backward through the text is a surprisingly large portion of the remaining
  45. //  10%, and if not supported, significantly reduces the usefulness of readers.  We
  46. //    therefore attempt to achieve this goal:
  47. //        3) Make "put back" a relatively efficient operation.  Make it possible to
  48. //        read backwards through the data structure.
  49. //    Often a client iterating over text will want to note the position of some character
  50. //    or token in the text.  We therefore set another goal:
  51. //        4) Support GetPosition ('tell') and SetPosition ('seek') operations.
  52. //    This last goal implies a specific need to handle the case where a client attempts to
  53. //    seek past the end of the text data structure.  In this case, to achieve efficiency,
  54. //    we invoke 2), by setting this requirement:
  55. //        5) It is acceptable to state in the contract that an attempt to SetPosition to
  56. //        an arbitrary position may fail.  However, a client can use GetLength to find
  57. //        the length of the data structure; it is safe to SetPosition to any value greater
  58. //        than or equal to zero, and less than the length of the data structure.
  59. //========================================================================================
  60.  
  61. //========================================================================================
  62. //    CLASS FW_CTextReader
  63. //
  64. //    A base class for iterators that read over a data structure containing characters.
  65. //
  66. //    It is possible to create a TextReader to read over any text data structure, as long
  67. //    as the following constraints are met:
  68. //
  69. //    1) It must be possible to get the total number of characters in the data structure
  70. //       at the time the text reader is constructed.
  71. //    1a) Of course, we assume that the length and content of the data structure does
  72. //        not change while the iterator is being used!
  73. //    2) The data members fStart, fLimit, and fNext are updated
  74. //
  75. //
  76. //    Invariant:
  77. //        ((fStart<=fNext) && (fNext<fLimit))
  78. //     || ((fStart-1==fNext) && (fBufferSum==0))
  79. //     || ((fNext==fLimit) && (fBufferSum==GetLength())
  80. //========================================================================================
  81.  
  82. class FW_CLASS_ATTR FW_CTextReader FW_AUTO_DESTRUCT_OBJECT
  83. {
  84.  
  85.   public:
  86.  
  87.     // ----- General
  88.     
  89.     virtual ~ FW_CTextReader();
  90.     FW_CTextReader(const FW_Byte*    chunk1Start,    // start of first contiguous chunk
  91.                    const FW_Byte*     chunk1Limit,    // limit of first contiguous chunk
  92.                    FW_ByteCount        totalLength);    // total bytes in data structure
  93.     
  94.     FW_ByteCount GetPosition(FW_Boolean inChars = FALSE);
  95.         // Get the current byte or character position, where 0 is first position in data structure.
  96.  
  97.     void SetPosition(FW_ByteCount position);
  98.         // Set the byte position to position.
  99.         // The result is undefined if position is outside the bounds of the data structure.
  100.  
  101.     virtual FW_CharacterCount GetLength();
  102.         // Get number of characters in data structure.
  103.  
  104.     FW_ByteCount GetByteLength();
  105.         // Get number of bytes in data structure.
  106.     
  107.     const FW_Byte* PeekByte() const;
  108.         // Return a pointer to the current byte without advancing. Can be used for lookahead.
  109.  
  110.     // ----- Byte-by-byte iteration
  111.  
  112.     FW_Char PeekCharacter();
  113.         // Return the current character (byte) without advancing.  
  114.         // Can be used for lookahead.
  115.  
  116.     FW_Char GetCharacterAndAdvance();
  117.         // Get the current character (byte) and advance.
  118.  
  119.     FW_Char BackupAndGetCharacter();
  120.         // Backup and get previous character (byte).
  121.  
  122.     // ----- Character-by-character iteration
  123.  
  124.     void Advance();
  125.         // Advance by one character.
  126.         
  127.     void Backup();
  128.         // Backup by one character.
  129.     
  130.     FW_LChar GetCharacterAndAdvance(FW_ByteCount& bytesInChar);
  131.         // Get the current character and advance.
  132.     
  133.     virtual FW_LChar PeekCharacter(FW_ByteCount& bytesInChar);
  134.         // Return the current character without advancing. 
  135.         // Assumes all input characters are the same width (fBytesPerChar).
  136.         // Override to handle variable-width characters.
  137.  
  138.     virtual FW_LChar BackupAndGetCharacter(FW_ByteCount& bytesInChar);
  139.         // Backup and get previous character.
  140.         // Assumes all input characters are the same width (fBytesPerChar).
  141.         // Override to handle variable-width characters.
  142.     
  143.     // ----- Chunky iteration
  144.     //     With chunky iteration, client is responsible for translating between bytes and characters.
  145.     //    The member functions FW_CTextReader::CharactersInBlock and FW_CTextReader::BytesToChars
  146.     //    may be used to do the translation.
  147.     
  148.     void Advance(FW_ByteCount delta);
  149.         // Advance by delta bytes.
  150.         
  151.     void Backup(FW_ByteCount delta);
  152.         // Backup by delta bytes.
  153.     
  154.     void PeekRunAhead(const FW_Byte*& start, FW_ByteCount& length);
  155.         // Peek ahead into current buffer of bytes without advancing.
  156.     
  157.     void PeekRunBehind(const FW_Byte*& end, FW_ByteCount& length);
  158.         // Peek behind into current buffer of bytes without backing up.
  159.         // end points one past "current" byte!
  160.  
  161.   protected:
  162.  
  163.     void GetNextBuffer();
  164.         // Calls DoGetNextBuffer, and updates fNext, fBufferSum.
  165.     
  166.     void GetPreviousBuffer();
  167.         // Calls DoGetPreviousBuffer, and updates fNext, fBufferSum.
  168.  
  169.     virtual void DoGetNextBuffer() = 0;
  170.         // Get another buffer from text data structure.
  171.         // Updates fStart and fLimit.
  172.         // Must ensure that fStart<=fLimit.
  173.  
  174.     virtual void DoGetPreviousBuffer() = 0;
  175.         // Gets previous buffer from text data structure.
  176.         // Updates fStart and fLimit.
  177.         // Must ensure that fStart<=fLimit.
  178.  
  179.     virtual FW_CharacterCount CharactersInBlock(const FW_Byte* last,
  180.                                                 const FW_Byte* first);
  181.  
  182.     const FW_Byte* PreviousByte(const FW_Byte* current, short delta);
  183.  
  184.     virtual FW_CharacterCount BytesToChars(const FW_ByteCount bytes);
  185.  
  186.     FW_ByteCount CharsToBytes(FW_CharacterCount length);
  187.  
  188.     FW_ByteCount BytesInBlock(const FW_Byte* last, const FW_Byte* first);
  189.  
  190.  
  191.     const FW_Byte    *fStart;        // Start of current buffer
  192.     
  193.     const FW_Byte    *fLimit;        // One past last byte of current buffer
  194.     
  195.     FW_ByteCount    fByteLength;    // Total bytes in data structure.
  196.  
  197.     FW_ByteCount    fBytesPerChar;    // Default value is sizeof(FW_Char)
  198.     
  199.   private:
  200.  
  201.     const FW_Byte    *fNext;            // Current position in buffer
  202.         
  203. #ifdef FW_DEBUG_TEXT_ITERATORS
  204.     void ClassInvariants() const;
  205. #else
  206.     void ClassInvariants() const {}    // Let compiler optimize away the empty inline
  207. #endif
  208.  
  209.     FW_ByteCount    fBufferSum;        // Total bytes in previous buffers.
  210. };
  211.  
  212. //========================================================================================
  213. //    CLASS FW_CTextWriter
  214. //
  215. //    TextWriters are (intentionally) kept simpler than TextReaders.  We assume that there
  216. //    is no need to allow backing up in order to rewrite.  This results in a smaller and
  217. //    simpler interface.
  218. //========================================================================================
  219.  
  220. enum FW_TextWriterMode {FW_kTextWriteOver, FW_kTextAppend};
  221.  
  222. class FW_CLASS_ATTR FW_CTextWriter FW_AUTO_DESTRUCT_OBJECT
  223. {
  224.   public:
  225.  
  226.     // ----- General
  227.     
  228.     virtual ~ FW_CTextWriter();
  229.         // Flush the current buffer.
  230.         // Writer destructors must do whatever may be necessary to restore text structure
  231.         // to valid state, e.g. restore NUL termination, cached length member, etc.
  232.  
  233.     FW_CTextWriter(FW_Byte *chunk1Start, // start of first contiguous chunk
  234.                    FW_Byte *chunk1Limit);// limit of first contiguous chunk
  235.     
  236.     FW_CharacterCount GetPosition();
  237.         // Get the current position, in characters.
  238.  
  239.     virtual void FlushAndUpdateText();
  240.         // Flush the current buffer.
  241.         // Call this method when done writing, or in the destructor.
  242.         // Override to do whatever may be necessary to restore the
  243.         // text data structure to a valid state.
  244.  
  245.     // ----- Character-by-character iteration
  246.  
  247.     void PutCharacterAndAdvance(FW_Char character);
  248.         // Write the character (byte) into the data structure and advance to next position.
  249.  
  250.     void PutCharacterAndAdvance(FW_LChar character, FW_ByteCount bytesInChar=0);
  251.         // Write the character into the data structure and advance to next position.
  252.         // Pass 0 for bytesInChar to use the default character size (fBytesPerChar)
  253.  
  254.     // ----- Chunky iteration
  255.     
  256.     void WritePeek(FW_Byte*& start, FW_ByteCount& length);
  257.         // Returns start address and length of buffer to write into.
  258.     
  259.     void WritePeekAdvance(const FW_Byte* start, FW_ByteCount bytesWritten);
  260.         // Inform iterator of number of bytes written into peek buffer
  261.         // start value must be same as returned by WritePeek
  262.         // No calls to PutCharacterAndAdvance between WritePeek and WritePeekAdvance!
  263.  
  264.   protected:
  265.  
  266.     virtual FW_CharacterCount BytesToChars(const FW_ByteCount bytes);
  267.  
  268.     virtual FW_CharacterCount CharactersInBlock(const FW_Byte* last,
  269.                                                 const FW_Byte* first);
  270.  
  271.     virtual void DoFlushBuffer(FW_ByteCount bytesToFlush) = 0;
  272.         // Flush the current buffer.
  273.  
  274.     virtual void DoGetNextBuffer() = 0;
  275.         // Get another buffer from text data structure, update fNext and fLimit.
  276.     
  277.     void FlushBuffer(FW_Boolean flushAll);
  278.         // Calls DoFlushBuffer to flush the current buffer, and updates fBufferSum.
  279.  
  280.     void FlushAndGetNextBuffer();
  281.         // Calls FlushBuffer and DoGetNextBuffer.
  282.         // Called when the buffer has filled up.
  283.  
  284.     FW_ByteCount        fBufferSum;        // Total characters flushed in previous buffers.
  285.     FW_Byte*            fStart;            // First byte in this buffer
  286.     FW_Byte*            fLimit;            // One past last byte of current buffer
  287.     FW_Byte*            fNext;            // Current position in buffer
  288.  
  289.     FW_ByteCount        fBytesPerChar;    // Default value is sizeof(FW_Char)
  290. };
  291.  
  292. //========================================================================================
  293. //    CLASS FW_CMemoryReader
  294. //
  295. //    A class for iterating over a buffer of characters.
  296. //========================================================================================
  297.  
  298. class FW_CLASS_ATTR FW_CMemoryReader : public FW_CTextReader
  299. {
  300. public:
  301.  
  302.     virtual ~ FW_CMemoryReader();
  303.     FW_CMemoryReader(const FW_Byte * buffer, FW_ByteCount bytes);
  304.     FW_CMemoryReader(const FW_Char * buffer, 
  305.                      FW_CharacterCount characters, 
  306.                      FW_ByteCount bytesPerChar=sizeof(FW_Char));
  307.     
  308. protected:
  309.  
  310.     virtual void DoGetNextBuffer();
  311.     virtual void DoGetPreviousBuffer();
  312.  
  313. };
  314.  
  315. //========================================================================================
  316. //    CLASS FW_CMemoryWriter
  317. //
  318. //    A class for writing into a buffer of characters.
  319. //========================================================================================
  320.  
  321. class FW_CLASS_ATTR FW_CMemoryWriter : public FW_CTextWriter
  322. {
  323. public:
  324.  
  325.     virtual ~ FW_CMemoryWriter();
  326.     FW_CMemoryWriter(FW_Byte * buffer, FW_ByteCount capacity);
  327.  
  328. protected:
  329.  
  330.     virtual void DoFlushBuffer(FW_ByteCount bytesToFlush);    // Override
  331.     virtual void DoGetNextBuffer();    // Override
  332.  
  333. };
  334.  
  335. //========================================================================================
  336. //    CLASS FW_CTextReader inlines
  337. //========================================================================================
  338.  
  339. //----------------------------------------------------------------------------------------
  340. //    FW_CTextReader::GetByteLength
  341. //----------------------------------------------------------------------------------------
  342.  
  343. inline FW_ByteCount FW_CTextReader::GetByteLength()
  344. {
  345.     return fByteLength;
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. //    FW_CTextReader::PeekRunAhead
  350. //----------------------------------------------------------------------------------------
  351.  
  352. inline void FW_CTextReader::PeekRunAhead(const FW_Byte*& start, FW_ByteCount& length)
  353. {
  354.     start = fNext;
  355.     length = fLimit-fNext;
  356. }
  357.  
  358. //----------------------------------------------------------------------------------------
  359. //    FW_CTextReader::PeekRunBehind
  360. //----------------------------------------------------------------------------------------
  361.  
  362. inline void FW_CTextReader::PeekRunBehind(const FW_Byte*& end, FW_ByteCount& length)
  363. {
  364.     end = fNext;
  365.     length = fNext-fStart;
  366. }
  367.  
  368. //----------------------------------------------------------------------------------------
  369. //    FW_CTextReader::Advance
  370. //----------------------------------------------------------------------------------------
  371.  
  372. inline void FW_CTextReader::Advance()
  373. {
  374.     this->Advance(fBytesPerChar);
  375. }
  376.  
  377. //----------------------------------------------------------------------------------------
  378. //    FW_CTextReader::Backup
  379. //----------------------------------------------------------------------------------------
  380.  
  381. inline void FW_CTextReader::Backup()
  382. {
  383.     this->Backup(fBytesPerChar);
  384. }
  385.  
  386. //----------------------------------------------------------------------------------------
  387. //    FW_CTextReader::BytesToChars
  388. //----------------------------------------------------------------------------------------
  389.  
  390. inline FW_CharacterCount FW_CTextReader::BytesToChars(const FW_ByteCount bytes)
  391. {
  392.     return bytes/fBytesPerChar;
  393. }
  394.  
  395. //----------------------------------------------------------------------------------------
  396. //    FW_CTextReader::CharsToBytes
  397. //----------------------------------------------------------------------------------------
  398.  
  399. inline FW_ByteCount FW_CTextReader::CharsToBytes(FW_CharacterCount length)
  400. {
  401.     return length*fBytesPerChar;
  402. }
  403.  
  404. //----------------------------------------------------------------------------------------
  405. //    FW_CTextReader::BytesInBlock
  406. //----------------------------------------------------------------------------------------
  407.  
  408. inline FW_ByteCount FW_CTextReader::BytesInBlock(const FW_Byte* last, const FW_Byte* first)
  409. {
  410.     return (last - first);
  411. }
  412.  
  413. //----------------------------------------------------------------------------------------
  414. //    FW_CTextReader::PeekByte
  415. //----------------------------------------------------------------------------------------
  416.  
  417. inline const FW_Byte* FW_CTextReader::PeekByte() const
  418. {
  419.     ClassInvariants();
  420.  
  421.     if (fNext>=fStart && fNext<fLimit)
  422.         return fNext;
  423.     else
  424.         return NULL;
  425. }
  426.  
  427. //----------------------------------------------------------------------------------------
  428. //    FW_CTextReader::PreviousByte
  429. //----------------------------------------------------------------------------------------
  430. inline const FW_Byte* FW_CTextReader::PreviousByte(const FW_Byte* current, short delta)
  431. {
  432.     return current - delta;
  433. }
  434.  
  435. //========================================================================================
  436. //    CLASS FW_CTextWriter inlines
  437. //========================================================================================
  438.  
  439. //----------------------------------------------------------------------------------------
  440. //    FW_CTextWriter::GetPosition
  441. //----------------------------------------------------------------------------------------
  442.  
  443. inline FW_ByteCount FW_CTextWriter::GetPosition()
  444. {
  445.     return fBufferSum + (fNext - fStart);
  446. }
  447.  
  448. //----------------------------------------------------------------------------------------
  449. //    FW_CTextWriter::FlushAndGetNextBuffer
  450. //----------------------------------------------------------------------------------------
  451.  
  452. inline void FW_CTextWriter::FlushAndGetNextBuffer()
  453. {
  454.     FlushBuffer(TRUE);        // flush entire buffer
  455.     DoGetNextBuffer();
  456. }
  457.  
  458. //----------------------------------------------------------------------------------------
  459. //    FW_CTextWriter::WritePeek
  460. //----------------------------------------------------------------------------------------
  461.  
  462. inline void FW_CTextWriter::WritePeek(FW_Byte*& start, FW_ByteCount& length)
  463. {
  464.     if (fNext >= fLimit)
  465.         FlushAndGetNextBuffer();
  466.     start = fNext;
  467.     length = fLimit-fNext;
  468. }
  469.  
  470. //----------------------------------------------------------------------------------------
  471. //    FW_CTextWriter::WritePeekAdvance
  472. //----------------------------------------------------------------------------------------
  473.  
  474. inline void FW_CTextWriter::WritePeekAdvance(const FW_Byte* start, FW_ByteCount bytesWritten)
  475. {
  476.     FW_ASSERT(start == fNext);
  477.     FW_ASSERT(bytesWritten <= fLimit-fNext);
  478.     fNext += bytesWritten;
  479. }
  480.  
  481. #if FW_LIB_EXPORT_PRAGMAS
  482. #pragma lib_export off
  483. #endif
  484.  
  485. #endif
  486.